package com.vc.videosdk;

import android.app.Activity;
import android.content.Context;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;

import androidx.annotation.Nullable;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.vc.videosdk.interfaces.VcStreamListener;
import com.vc.videosdk.utils.KeyboardUtil;
import com.vc.videosdk.utils.VideoInfoCalculateUtil;
import com.vc.videosdk.xlog.XLogUtil;

import org.vclusters.ClustersSurfaceView;
import org.vclusters.MediaStream;
import org.vclusters.network.NetWork;
import org.webrtc.DataChannel;

import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import keyboard.InputMethodBean;
import keyboard.KeyboardInfoBean;

/**
 * @Author : wy
 * @Time : On 2024/9/26 10:16
 * @Description : VcSurfaceView
 */
public class VcSurfaceView extends ClustersSurfaceView implements MediaStream.MediaStreamClientEvents {

    private VcStreamListener mVcStreamListener;
    private EditText mEdt;
    private Activity mActivity;
    private boolean isAutoEdit = false;
    private Timer mTimer;
    //重连次数
    private int mReconnecStreamCounts=5;
    //当前尝试重连次数
    private int mCurrentConnectCount;


    public VcSurfaceView(Context context) {
        super(context);
    }

    public VcSurfaceView(Context context, AttributeSet set) {
        super(context, set);
//        mEditText=new EditText(context);
//        mEditText.setWidth(200);  // 设置宽度为200像素
//        mEditText.setHeight(200); // 设置高度为200像素
//        mEditText.setLayoutParams(new LinearLayout.LayoutParams(200, 200));
//        mEditText.setVisibility(GONE);

    }

    public void setVcStreamListener(VcStreamListener listener) {
        super.setClientEvents(this);
        mVcStreamListener = listener;
    }


    public boolean setIceServer(Map<NetWork.NETWORKNAME, String> iceServerNetwork) {
        return super.setIceServer(iceServerNetwork);
    }

    public void setActivity(Activity activity) {
        super.setActivity(activity);
        mActivity = activity;
    }

    public void setCloubKeyEdt(EditText edt) {
        initEditText(edt);
    }

    public void setClientEvents(MediaStream.MediaStreamClientEvents mediaStreamClientEvents) {
        super.setClientEvents(mediaStreamClientEvents);
    }

    /**
     * @param uri                       信令服务器地址
     * @param room                      需要拉流设备所在的房间---卡instanceId/sn
     * @param videoCodec                视频编码 “H264 Baseline” :h264标清编码 “H264 High”:h264高清编码 “VP8”：VP8编码 “VP9”：VP9编码 “AV1”：AV1编码 “H265”:H265编码
     * @param fps                       帧率
     * @param bitrate                   码率
     * @param width                     视频宽
     * @param height                    视频高
     * @param localVideoCallEnabled     本地是否发送视频
     * @param localAudioCallEnabled     本地是否发送音频
     * @param localVideoReceiveEnabled  本地是否接收视频
     * @param localAudioReceiveEnabled  本地是否接收音频
     * @param remoteVideoCallEnabled    远端是否发送视频
     * @param remoteAudioCallEnabled    远端是否发送音频
     * @param remoteVideoReceiveEnabled 远端是否接收视频
     * @param remoteAudioReceiveEnabled 远端是否接收音频
     * @param cardWidth                 设置卡分辨的宽
     * @param cardHeight                设置卡分辨的高
     * @param cardDensity               设置卡的密度
     * @param authToken                 鉴权，设置vclusters则跳过鉴权
     * @return 成功则不为空，名字可以做唯一标识在MediaStreamClientEvents回调中以该名字区分是哪一路的回调
     */

    String mUri;
    String mInstanceId;
    String mVideoCodec;
    int mFps;
    int mBitrate;
    int mWidth;
    int mHeight;
//    int mCardWidth;
//    int mCardHeight;
//    int mCardDensity;
    String mAuthToken;

    public String startConnect(String uri, String room, String videoCodec, int fps, int bitrate, int width, int height,  String authToken) {
        mUri = uri;
        mInstanceId = room;
        mVideoCodec = videoCodec;
        mFps = fps;
        mBitrate = bitrate;
        mWidth = width;
        mHeight = height;
        mAuthToken = authToken;
        return start(uri, room, videoCodec, fps, bitrate, width, height, true, true, true, true, true, true, true, true, 0, 0, 0, authToken);
    }

    /**
     * 断开连接
     * ClustersSurfaceView 是控件类型则一定要在 ui 线程中执行 stop，否则会崩溃
     */
    public void stopConnect() {
        XLogUtil.INSTANCE.e("VcSurfaceView stopConnect()");
        if(mActivity!=null){
            mActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    stop();
                }
            });
        }else {
            XLogUtil.INSTANCE.e("VcSurfaceView stopConnect() fail,exception:mActivity==null");
        }

    }


    /**
     * 设置音量加减等
     *
     * @param value
     */
    public void sendKey(int value) {
        super.sendKey(value);
    }


    @Override
    public void onVideoInfo(String s) {

    }

    public void setKeyEditView(EditText edt) {
        mEdt = edt;
    }

    @Override
    public void onChannelData(DataChannel.Buffer buffer, String peerName) {
        //{"type":"keyboardFeedbackBean","data":{"viewLocation":0,"type":589825}}
        if (buffer.binary == false) {
            String jsonString = StandardCharsets.UTF_8.decode(buffer.data).toString();
            XLogUtil.INSTANCE.d( "VcSurfaceView onChannelData jsonString :" + jsonString);
            JSONObject jsonObject = JSON.parseObject(jsonString);
            String typeValue = jsonObject.getString("type");
            if (!typeValue.isEmpty()) {
                if (typeValue.equals("keyboardFeedbackBean")) {
                    XLogUtil.INSTANCE.d("VcSurfaceView 收到调起键盘通知");
                    if (mActivity != null) {
                        mActivity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                showKeyboard();
                            }
                        });
                    } else {
                        XLogUtil.INSTANCE.e("VcSurfaceView showKeyboard fail,mActivity==null");
                    }

                } else if (typeValue.equals("KeyboardHidden")) {
                    XLogUtil.INSTANCE.d("VcSurfaceView 收到隐藏键盘通知");
                    if (mActivity != null) {
                        mActivity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                hideKeyBoard();
                            }
                        });
                    } else {
                        XLogUtil.INSTANCE.e("VcSurfaceView hideKeyBoard fail,mActivity==null");
                    }
                }
            }
        }
    }


    /**
     * 音视频通道连接成功时
     *
     * @param peerName 连接名(多路拉流时可通过该字符判断是哪一路回调)
     */
    @Override
    public void onIceConnected(String peerName) {
        XLogUtil.INSTANCE.d("VcSurfaceView onIceConnected() 音视频通道连接成功");
        if (mVcStreamListener != null) {
            mVcStreamListener.onIceConnected(peerName);
        }

       // stopTimeReConnect();

        //设置输入法类型,1---真机键盘
        InputMethodBean.Data inputMethodBeanData = new InputMethodBean.Data(1);
        InputMethodBean inputMethodBean = new InputMethodBean("InputMethod", inputMethodBeanData);
        sendData(JSONObject.toJSONString(inputMethodBean));
    }

    @Override
    public void onIceDisconnected(String s) {
        //调用stop  视频断开 执行重连   中转服务不通，会调
        XLogUtil.INSTANCE.d("VcSurfaceView onIceDisconnected 断开连接，通知上层执行重连...");
        if(mVcStreamListener!=null){
            mVcStreamListener.onAbnormalDisconnected();
        }
//        try{
//           timeReConnect();
//        }catch(Exception e){
//            XLogUtil.INSTANCE.e("VcSurfaceView reConnectStream() Exception:"+e.getMessage());
//        }

    }

    @Override
    public void onFrameResolutionChanged(int i, int i1, int i2) {

    }

    @Override
    public void onDisConnected(String peerName) {
        //调用stop 信令断开回调给客户，不需要重连
        //信令服务器异常---返回该信息给客户
        XLogUtil.INSTANCE.d("VcSurfaceView onDisConnected() 信令服务器异常 peerName="+peerName);
        if (mVcStreamListener != null) {
            mVcStreamListener.onDisConnected(peerName);
        }
    }

    @Override
    public String onNatsData(String s, String s1) {
        return null;
    }


    @Override
    public void onAuthResult(String peerName, int code, String descriptions) {
        //peerName:连接名 code:状态码 (0:成功 1:失败) descriptions:失败原因
        XLogUtil.INSTANCE.d("VcSurfaceView onAuthResult code:"+code);
        if (mVcStreamListener != null) {
            mVcStreamListener.onAuthResult(peerName, code, descriptions);
        }
    }

    @Override
    public void onStatsDeliverd(String str) {
        VideoInfoCalculateUtil.INSTANCE.getRoundTripTime(str, new VideoInfoCalculateUtil.VideoInfoListener() {
            @Override
            public void callbackStatus(@Nullable Integer frameWidth, @Nullable Integer frameHeight, @Nullable String frameRate, float delay, int receivePerSecond, double packetLossRate) {
                if (mVcStreamListener != null) {
                    mVcStreamListener.streamInfo(frameWidth,frameHeight,frameRate,delay,receivePerSecond,packetLossRate);
                }
            }
        });
    }

    @Override
    public void onChannelConnect() {

    }

    @Override
    public void onConnectedError(String s, String s1) {

    }

    @Override
    public void onCameraOpen() {

    }

    @Override
    public void onAudioOpen() {

    }

    /**
     * 发送键盘数据
     *
     * @param KeyBoardData
     * @param position
     */
    public void sendKeyboardContent(String KeyBoardData, int position) {
        KeyboardInfoBean.Data keyboardInfoData = new KeyboardInfoBean.Data(KeyBoardData, position);
        KeyboardInfoBean keyboardInfoBean = new KeyboardInfoBean("KeyoardInfo", keyboardInfoData);
        sendData(JSONObject.toJSONString(keyboardInfoBean));
        XLogUtil.INSTANCE.d("VcSurfaceView keyboard 发送键盘数据 KeyBoardData:" + JSONObject.toJSONString(keyboardInfoBean));
    }


    /**
     * 初始化键盘透传需要的edt
     *
     * @param edt
     */
    private void initEditText(EditText edt) {
        if (edt == null) {
            XLogUtil.INSTANCE.e("VcSurfaceView initEditText fail,edt==null,键盘透传将不可用");
            return;
        }
        mEdt = edt;
        mEdt.setOnKeyListener(new OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (event == null) {
                    return false;
                }
                XLogUtil.INSTANCE.d("VcSurfaceView keyboard setOnKeyListener KeyEvent:" + event);
                //删除键
                if (keyCode == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN) {
                    XLogUtil.INSTANCE.d("VcSurfaceView keyboard KeyEvent.KEYCODE_DEL");
                    sendKeyboardContent("", -1);
                    return true;
                } else if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN) {
                    XLogUtil.INSTANCE.d("VcSurfaceView SteamKeyboardUtils KeyEvent.KEYCODE_ENTER");
                    //回车键
                    editFinish();
                    return true;
                }
                return false;
            }
        });


        mEdt.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                XLogUtil.INSTANCE.d("keyboard  keyEvent:" + event);
                //回车键
                if (actionId == EditorInfo.IME_ACTION_DONE) {
                    editFinish();
                    return true;
                }
                return false;
            }
        });

        mEdt.removeTextChangedListener(mTextWatcher);
        mEdt.addTextChangedListener(mTextWatcher);
    }


    /**
     * 编辑结束键盘收起
     */
    private void editFinish() {
        hideKeyBoard();
    }


    private TextWatcher mTextWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
//            if (isAutoEdit) {
//                isAutoEdit = false;
//                return;
//            }
            try {
                if (!TextUtils.isEmpty(charSequence)) {
                  //  XLogUtil.INSTANCE.d("VcSurfaceView onTextChanged editTextData:" + charSequence + ",,,start:" + start + ",,,before:" + before + ",,,count:" + count);
                    if ((charSequence.length() > (start + before))) {
                        //走新增
                        String editTextData = charSequence.toString().substring(start + before);
                       // XLogUtil.INSTANCE.d("VcSurfaceView keyboard 新增内容 editTextData:" + editTextData);
                        sendKeyboardContent(editTextData, 1);

                    } else if (charSequence.length() < (start + before)) {
                        //走删除
                        sendKeyboardContent("", -1);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void afterTextChanged(Editable s) {

        }
    };


    /**
     * 调起键盘
     */
    private void showKeyboard() {
        // isAutoEdit = true;
        if (mEdt != null) {
            try {
                KeyboardUtil.showSoftInput(mEdt);
            } catch (Exception e) {
                XLogUtil.INSTANCE.e("VcSurfaceView showSoftInput Exception:" + e.getMessage());
            }

        }
    }


    /**
     * 隐藏键盘
     *
     * @param
     */
    private void hideKeyBoard() {
//        if(softKeyboardStateHelper?.isSoftKeyboardOpened == false){
//            return
//        }
        try {
            if (mEdt != null) {
                KeyboardUtil.hideSoftInput(mEdt);
            }
        } catch (Exception e) {
            XLogUtil.INSTANCE.e("VcSurfaceView showSoftInput Exception:" + e.getMessage());
        }
    }


    /**
     * 重连
     */
    public void timeReConnect() {
        try {
            if (mTimer == null) {
                mTimer = new Timer();
            }

            mTimer.schedule(new TimerTask() {
                @Override
                public void run(){
                    mCurrentConnectCount++;
                    if(mCurrentConnectCount<=mReconnecStreamCounts){
                        if(mActivity!=null){
                            mActivity.runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    //每次重连前，要先断连再重连
                                    stopConnect();
                                    reConnectStream(mCurrentConnectCount);
                                }
                            });
                        }
                    }else {
                        stopTimeReConnect();
                        XLogUtil.INSTANCE.e("VcSurfaceView do reConnectStream fail reconnecStreamCounts="+mReconnecStreamCounts);
                    }
                }
            }, 1000 * 5L, 1000 * 5L);
        } catch (Exception e) {
            XLogUtil.INSTANCE.e("VcSurfaceView timeReConnect Exception:" + e.getMessage());
        }
    }


    /**
     * 断连后重连流
     * @return
     */
    public String reConnectStream(int count) {
        XLogUtil.INSTANCE.d("VcSurfaceView reConnectStream 第"+count+"次重连:mUri:"+mUri+",,,mInstanceId:"+mInstanceId+",,,mVideoCodec:"+mVideoCodec+",,,mFps:"+mFps+",,,mBitrate:"+mBitrate+",,,mWidth:"+mWidth+",,,mHeight:"+mHeight+",,,mAuthToken:"+mAuthToken);
        return start(mUri, mInstanceId, mVideoCodec, mFps, mBitrate, mWidth, mHeight, true, true, true, true, true, true, true, true, 0, 0, 0, mAuthToken);
    }


    /**
     * 停止重连
     */
    private void stopTimeReConnect() {
        mCurrentConnectCount=0;
        if (mTimer != null) {
            XLogUtil.INSTANCE.d("VcSurfaceView stopTimeReConnect()");
            mTimer.cancel();
            mTimer=null;
        }
    }


    /**
     * 设置重连次数
     * @param count
     */
//    public void setReconnecStreamCounts(int count){
//        XLogUtil.INSTANCE.d("VcSurfaceView setReconnecStreamCounts count:"+count);
//        mReconnecStreamCounts=count;
//    }


    /**
     * 设置流分辨率
     * @param width
     * @param height
     * @param density
     */
    public void setVideoSize(int width, int height, int density) {
       super.setVideoSize(width,height,density);
    }

}
